package com.lovo.result;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Component;

import javax.persistence.OptimisticLockException;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class ResultAspect {
    @AfterThrowing(value = "execution(* com.lovo.service..*(..))", throwing = "e")
    public void exceptionHandler(Throwable e) throws Throwable {
        e.printStackTrace();
        log.error(e.getMessage() + " : " + e);
        ResultCode resultCode = null;
        if (e instanceof OptimisticLockException) {
            resultCode = ResultCode.SERVER_OPTIMISTIC_LOCK_ERROR;
        } else if (e instanceof EmptyResultDataAccessException) {
            resultCode = ResultCode.SERVER_EMPTY_RESULT_DATA_ACCESS_ERROR;
        } else if (e instanceof GlobalHandleException) {
            resultCode = ((GlobalHandleException) e).getResultCode();
        } else {
            resultCode = ResultCode.SERVER_INNER_ERROR;
        }
        throw new GlobalHandleException(resultCode);

    }

    @Around("execution(* com.lovo.controller..*(..))")
    public Object generateResult(ProceedingJoinPoint joinPoint) throws Throwable {

        Object obj = null;
        Class clazz = null;
        Method targetMethod = null;
        try {
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            targetMethod = methodSignature.getMethod();
            clazz = joinPoint.getTarget().getClass();

            obj = joinPoint.proceed(joinPoint.getArgs());
            //判断类上是否加了注解
            if (clazz.isAnnotationPresent(ResponseResult.class)
                    || targetMethod.isAnnotationPresent(ResponseResult.class)) {
                obj = ResultVO.success(obj);
            }
        } catch (GlobalHandleException e) {
            e.printStackTrace();
            log.error(e.getMessage() + e);
            if (clazz.isAnnotationPresent(ResponseResult.class)
                    || targetMethod.isAnnotationPresent(ResponseResult.class)) {
                obj = ResultVO.fail(e.getResultCode());
            } else {
                throw e;
            }
        } catch (Throwable e) {
            e.printStackTrace();
            log.error(e.getMessage() + e);
            if (clazz.isAnnotationPresent(ResponseResult.class)
                    || targetMethod.isAnnotationPresent(ResponseResult.class)) {
                obj = ResultVO.fail(ResultCode.SERVER_UNKNOW_ERROR);
            } else {
                throw e;
            }
        }

        return obj;
    }
}
